/*
 * Copyright 2007-2010 Jeremy Brown.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @author <a href="http://jeremy-brown.com">Jeremy Brown</a>
 */


package groovy.prefuse.factory

//import groovy.prefuse.impl.controls.*

import prefuse.*
import prefuse.controls.*

public class ControlFactory extends AbstractFactory
{
	private Class klass
	
	public ControlFactory(Class klass)
	{
		this.klass = klass
	}
	
	boolean isLeaf()
	{
		return true
	}
    
    public Object newInstance(FactoryBuilderSupport builder, Object name, Object value, Map attributes) throws InstantiationException, IllegalAccessException
	{
		if(value == null && attributes.control)
		{
			value = attributes.remove("control")
		}
				
		if(value instanceof ControlAdapter)
		{
			return value
		}
		
		def buildClass
		if(klass)
		{
			buildClass = klass
		}
		else if(value instanceof Class)
		{
			buildClass = value
			value = null
		}

		
		def control = null

		if(buildClass instanceof Class && ControlAdapter.isAssignableFrom(buildClass))
		{
			if(ControlAdapter.equals(buildClass))
			{
				//Create a ClosureControlAdapter and pass in any overriding methods from the attributes map
				def methodMap = [:]
				attributes.keySet().grep(~/^(item|key|mouse).*/).each{key->methodMap[key] = attributes.remove(key)}
				control = methodMap as ControlAdapter
			}
			else if(AnchorUpdateControl.equals(buildClass))
			{
				def layout = attributes.layout
				if(!(layout instanceof List))
				{
					layout = [layout]
				}
				
				if(layout && attributes.action && attributes.overItem != null)
				{
					control = new AnchorUpdateControl(layout, attributes.remove("action"), attributes.remove("overItem"))
				}
				else if(layout && attributes.action)
				{
					control = new AnchorUpdateControl(layout, attributes.remove("action"))
				}
				else if(layout)
				{
					control = new AnchorUpdateControl(layout)
				}
			}
			else if(DragControl.equals(buildClass))
			{
				if(attributes.repaint != null && attributes.fixOnMouseOver != null)
				{
					control = new DragControl(attributes.remove("repaint"), attributes.remove("fixOnMouseOver"))
				}
				else if(attributes.action && attributes.fixOnMouseOver != null)
				{
					control = new DragControl(attributes.remove("action"), attributes.remove("fixOnMouseOver"))
				}
				else if(attributes.repaint != null)
				{
					control = new DragControl(attributes.remove("repaint"))
				}
				else if(attributes.action)
				{
					control = new DragControl(attributes.remove("action"))
				}
				else
				{
					control = new DragControl()
				}
			}
			else if(FocusControl.equals(buildClass))
			{
				def focusGroup = null
				if(attributes.focusGroup != null){focusGroup = attributes.remove("focusGroup")}
				else if(attributes.group != null){focusGroup = attributes.remove("group")}
				
				if(focusGroup && attributes.clicks && attributes.action)
				{
					control = new FocusControl(focusGroup, attributes.remove("clicks"), attributes.remove("action"))
				}
				else if(focusGroup && attributes.clicks)
				{
					control = new FocusControl(focusGroup, attributes.remove("clicks"))
				}
				if(focusGroup && attributes.clicks && attributes.action)
				{
					control = new FocusControl(focusGroup)
				}
				else if(attributes.clicks && attributes.action)
				{
					control = new FocusControl(attributes.remove("clicks"), attributes.remove("action"))
				}
				else if(attributes.clicks)
				{
					control = new FocusControl(attributes.remove("clicks"))
				}
				else
				{
					control = new FocusControl()
				}
			}
			else if(HoverActionControl.equals(buildClass))
			{
				control = new HoverActionControl(attributes.remove("action"))
			}
			else if(NeighborHighlightControl.equals(buildClass))
			{
				if(attributes.action)
				{
					control = new NeighborHighlightControl(attributes.remove("action"))
				}
				else
				{
					control = new NeighborHighlightControl()
				}
			}
			else if(PanControl.equals(buildClass))
			{
				if(attributes.button && attributes.panOverItem != null)
				{
					control = new PanControl(attributes.remove("button"), attributes.remove("panOverItem"))
				}
				else if(attributes.button)
				{
					control = new PanControl(attributes.remove("button"))
				}
				else if(attributes.panOverItem)
				{
					control = new PanControl(attributes.remove("panOverItem"))
				}
				else
				{
					control = new PanControl()
				}
			}
			else if(RotationControl.equals(buildClass))
			{
				if(attributes.button)
				{
					control = new RotationControl(attributes.remove("button"))
				}
				else
				{
					control = new RotationControl()
				}
			}
			else if(ToolTipControl.equals(buildClass))
			{
				def fields = null
				if(value != null){fields = value}
				else if(attributes.field != null){fields = attributes.remove("field")}
				else if(attributes.fields != null){fields = attributes.remove("fields")}
				if(fields instanceof List)
				{
					control = new ToolTipControl(fields as String[])
				}
				else
				{
					control = new ToolTipControl([fields] as String[])
				}
			}
			else if(ZoomControl.equals(buildClass))
			{
				if(attributes.button)
				{
					control = new ZoomControl(attributes.remove("button"))
				}
				else
				{
					control = new ZoomControl()
				}
			}
			else if(ZoomingPanControl.equals(buildClass))
			{
				if(attributes.repaint != null)
				{
					control = new ZoomingPanControl(attributes.remove("repaint"))
				}
				else
				{
					control = new ZoomingPanControl()
				}
			}
			else if(ZoomToFitControl.equals(buildClass))
			{
				if(attributes.group && attributes.margin && attributes.duration && attributes.button)
				{
					control = new ZoomToFitControl(attributes.remove("group"), attributes.remove("margin"), attributes.remove("duration"), attributes.remove("button"))
				}
				else if(attributes.group && attributes.button)
				{
					control = new ZoomToFitControl(attributes.remove("group"), attributes.remove("button"))
				}
				else if(attributes.group)
				{
					control = new ZoomToFitControl(attributes.remove("group"))
				}
				else if(attributes.button)
				{
					control = new ZoomToFitControl(attributes.remove("button"))
				}
				else
				{
					control = new ZoomToFitControl()
				}
			}

			////////////////////////////////////////////////////////////////////////////////////////
			//DocuBurst extension: http://www.cs.utoronto.ca/~ccollins/research/docuburst/index.html
			//MouseWheelControl
			////////////////////////////////////////////////////////////////////////////////////////
			
			else if(builder.getRadialSpaceFillingTreeRegistered() && (ca.utoronto.cs.prefuseextensions.control.MouseWheelControl).equals(buildClass))
			{
				if(attributes.action && attributes.field && attributes.min != null && attributes.max != null && attributes.increment != null)
				{
					control = new ca.utoronto.cs.prefuseextensions.control.MouseWheelControl(attributes.remove("action"), attributes.remove("field"), attributes.remove("min"), attributes.remove("max"), attributes.remove("increment"))
				}
				else if(attributes.action && attributes.field)
				{
					control = new ca.utoronto.cs.prefuseextensions.control.MouseWheelControl(attributes.remove("action"), attributes.remove("field"))
				}
				else
				{
					control = new ca.utoronto.cs.prefuseextensions.control.MouseWheelControl()
				}
			}
				
			//constructors that require no parameters
			else if(
				SubtreeDragControl.equals(buildClass) ||
				WheelZoomControl.equals(buildClass)
			)
			{
				control = buildClass.newInstance()
			}
			
			//Try to instantiate the Control with a no-parameter-constructor
			else
			{
				control = buildClass.newInstance()
			}
		}
		else
		{
			//Create a ClosureControlAdapter and pass in any overriding methods from the attributes map
			def methodMap = [:]
			attributes.keySet().grep(~/^(item|key|mouse).*/).each{key->methodMap[key] = attributes.remove(key)}
			control = methodMap as ControlAdapter
		}
		
		return control
	}

	
    public void setParent(FactoryBuilderSupport builder, Object parent, Object child) 
	{
		if(parent instanceof Display)
		{
			parent.addControlListener(child)
		}
    }
	
	

}
